home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Games / Mac Game Developer's Handbook / Game Utils & Sample Apps / Kill Apps Sample Code / KillEveryOneButMe.c next >
Encoding:
C/C++ Source or Header  |  1992-03-31  |  20.3 KB  |  562 lines  |  [TEXT/MPS ]

  1. /* KillEveryBodyButMe.c */
  2. /* Some folks want to kill all the other applications running on a machine */
  3. /* for demos, school situations, kiosks, etc. */
  4. /* with System 7, it's easy, just use the Process Manager and AppleEvents. */
  5. /* This thing shows you how. */
  6. /* PLEASE don't abuse this.  System 7 gives the user full-time multiFinder, and they */
  7. /* like it, our System Software team worked very hard to make this */
  8. /* happen.  ONLY do this in very special circumstances, or you're taking */
  9. /* power away from the user and weaking the strength of the Mac. */
  10. /* Written  by C.K. Haun <TR> */
  11. /* Apple Developer Tech Support */
  12.  
  13. /* Of course, Copyright 1991, Apple Computer Inc. */
  14. #if 0
  15. #include <Types.h>
  16. #include <memory.h>
  17. #include <Packages.h>
  18. #include <Errors.h>
  19. #include <quickdraw.h>
  20. #include <fonts.h>
  21. #include <dialogs.h>
  22. #include <windows.h>
  23. #include <menus.h>
  24. #include <events.h>
  25. #include <OSEvents.h>
  26. #include <Desk.h>
  27. #include <diskinit.h>
  28. #include <OSUtils.h>
  29. #include <resources.h>
  30. #include <toolutils.h>
  31. #include <AppleEvents.h>
  32. #include <EPPC.h>
  33. #include <GestaltEqu.h>
  34. #include <PPCToolbox.h> 
  35. #include <Processes.h>
  36. #include <Balloons.h>
  37. #endif 
  38. #pragma load "Ram Disk:dumpheaders"
  39. /* prototypes */
  40. void InitalizeApp(void);
  41. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  42. void DrawMain(WindowPtr drawIt);
  43. Boolean DoSelected(long val);
  44.  
  45. void InitAEStuff(void);
  46. void DoHighLevel(EventRecord *AERecord);
  47. void DoDaCall(MenuHandle themenu, long theit);
  48. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  49. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  50. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  51. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  52. void SampleHelpDialog(void);
  53. void KillEveryBody(void);
  54. /* one external */
  55. extern void _DataInit();                                    /* this is the C initialization code */
  56.  
  57. #define kMBarID 128
  58. #define kAppleMenu 128
  59. #define kFileMenu 129
  60. #define kEditMenu 130
  61. #define kToolsMenu 131
  62. #define kResumeMask             1       /* bit of message field for resume vs. suspend */
  63. #define kSampHelp 129
  64. #define kAboutBox 128
  65. #define kHelpString 128
  66. #define kNewItem 1
  67. #define kOpenItem 2
  68. #define kCloseItem 3
  69. #define kSaveItem 4
  70. #define kSaveAsItem 5
  71. #define kFileBlank1 6
  72. #define kPageSetupItem 7
  73. #define kPrintItem 8
  74. #define kFileBlank2 9
  75. #define kQuitItem 10
  76. #define kBadSystem 130
  77. #define kTitle 129
  78. struct AEinstalls {
  79.     AEEventClass theClass;
  80.     AEEventID theEvent;
  81.     EventHandlerProcPtr theProc;
  82. };
  83. typedef struct AEinstalls AEinstalls;
  84.  
  85. Handle gMymenu;                                             /* my menu bar handle */
  86. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle;
  87. Boolean gQuit, gInBackground;
  88. EventRecord gERecord;
  89. AEDesc gTheAddress;
  90. WindowPtr myWindow;
  91. ProcessSerialNumber gOurSN;
  92. short gHelpItem;
  93.  
  94. #pragma segment Main
  95. main()
  96. {
  97.     WindowPtr twindow;
  98.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  99.     InitalizeApp();
  100.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  101.     do {
  102.         WaitNextEvent(everyEvent, &gERecord, 30, nil);
  103.         switch (gERecord.what) {
  104.             
  105.             case nullEvent:
  106.                 /* no nul processing in this sample */
  107.                 break;
  108.             case updateEvt:
  109.                 DrawMain((WindowPtr)gERecord.message);      /* draw whatever window needs an update */
  110.                 break;
  111.             case mouseDown:
  112.                 /* first see where the hit was */
  113.                 switch (FindWindow(gERecord.where, &twindow)) {
  114.                     
  115.                     case inDesk:                            /* if they hit in desk, then the process manager */
  116.                         break;                              /* will switch us out, we don't need to do anything */
  117.                     case inMenuBar:
  118.                         DoSelected(MenuSelect(gERecord.where));
  119.                         break;
  120.                         
  121.                     case inSysWindow:
  122.                         /* pass to the system */
  123.                         SystemClick(&gERecord, twindow);
  124.                         break;
  125.                     case inContent:
  126.                         /* Handle content and control clicks here */
  127.                         break;
  128.                     case inDrag:
  129.                         if (twindow == FrontWindow())
  130.                             DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  131.                         break;
  132.                     case inGrow:
  133.                         /* Call GrowWindow here if you have a grow box */
  134.                         break;
  135.                     case inGoAway:
  136.                         /* Click in Close box */
  137.                         break;
  138.                         
  139.                 }
  140.             case mouseUp:
  141.                 /* don't care */
  142.                 break;
  143.                 /* same action for key or auto key */
  144.             case keyDown:
  145.             case autoKey:
  146.                 if (gERecord.modifiers & cmdKey)
  147.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  148.                 break;
  149.             case keyUp:
  150.                 /* don't care */
  151.                 break;
  152.             case diskEvt:
  153.                 /* I don't do anything special for disk events, this just passes them */
  154.                 /* to a function that checks for an error on the mount */
  155.                 DoDiskEvents(gERecord.message);
  156.                 break;
  157.             case activateEvt:
  158.                 if (gERecord.modifiers & activeFlag)
  159.                     DrawMain((WindowPtr)gERecord.message);
  160.                 break;
  161.             case networkEvt:
  162.                 /* don't care */
  163.                 break;
  164.             case driverEvt:
  165.                 /* don't care */
  166.                 break;
  167.             case app4Evt:
  168.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  169.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  170.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  171.                         break;
  172.                 }
  173.                 break;
  174.             default:
  175.                 break;
  176.                 /* This dispatches high level events (AppleEvents, for example) */
  177.                 /* to our dispatch routine.  This is NEW in the event loop for */
  178.                 /* System 7 */
  179.             case kHighLevelEvent:
  180.                 DoHighLevel(&gERecord);
  181.                 break;
  182.                 
  183.         }
  184.     }
  185.             while (gQuit != true);
  186.     
  187. }
  188.  
  189. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  190. /* like to perform some action or just know when a DA is opened in your */
  191. /* layer.  Can be handy to track memory problems when a DA is opened */
  192. /* with an Option-open */
  193. void DoDaCall(MenuHandle themenu, long theit)
  194. {
  195.     long qq;
  196.     char DAname[255];
  197.     GetItem(themenu, theit, &DAname);
  198.     qq = OpenDeskAcc(DAname);
  199. }
  200.  
  201. /* end DoDaCall */
  202.  
  203. /* DoDiskEvents just checks the error code from the disk mount, */
  204. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  205. /* You can do much more here if you care about what disks are */
  206. /* in the drive */
  207. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  208. {
  209.     short hival, loval, tommy;
  210.     Point fredpoint =  {
  211.         40, 40
  212.     };
  213.     hival = HiWord(dinfo);
  214.     loval = LoWord(dinfo);
  215.     if (hival != noErr)                                     /* something happened */ {
  216.         tommy = DIBadMount(fredpoint, dinfo);
  217.     }
  218. }
  219.  
  220. /* draws my window.  Pretty simple */
  221. void DrawMain(WindowPtr drawIt)
  222. {
  223.     short vPos, hPos;
  224.     short incre = 20;
  225.     short oldFace;
  226.     ProcessInfoRec infoRec;
  227.     StringHandle theString;
  228.     OSErr myErr;
  229.     Str31 processName;
  230.     FSSpec procSpec;
  231.     ProcessSerialNumber processSN;
  232.     processSN.lowLongOfPSN = kNoProcess;
  233.     processSN.highLongOfPSN = kNoProcess;
  234.     vPos = 15;
  235.     hPos = 20;
  236.     BeginUpdate(drawIt);
  237.     SetPort(drawIt);
  238.     EraseRect(&drawIt->portRect);
  239.     MoveTo(hPos, vPos);
  240.     theString = GetString(kTitle);
  241.     HLock((Handle)theString);
  242.     oldFace = drawIt->txFace;
  243.     TextFace(bold);
  244.     DrawString((ConstStr255Param)*theString);
  245.     TextFace(oldFace);
  246.     ReleaseResource((Handle)theString);
  247.     vPos += incre;
  248.     do {
  249.         myErr = GetNextProcess(&processSN);
  250.         
  251.         infoRec.processInfoLength = sizeof(ProcessInfoRec);
  252.         infoRec.processName = &processName;
  253.         infoRec.processAppSpec = &procSpec;
  254.         myErr = GetProcessInformation(&processSN, &infoRec);
  255.         if (!myErr) {
  256.             MoveTo(hPos, vPos);
  257.             DrawString(infoRec.processName);
  258.             vPos += incre;
  259.         }
  260.     }
  261.             while (myErr == noErr);
  262.     
  263.     EndUpdate(drawIt);
  264. }
  265.  
  266. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  267. /* mught be handy someday */
  268. Boolean DoSelected(long val)
  269. {
  270.     short loval, hival;
  271.     Boolean returnVal = false;
  272.     loval = LoWord(val);
  273.     hival = HiWord(val);
  274.     
  275.     switch (hival) {                                        /* switch off the menu number selected */
  276.         case kAppleMenu:                                    /* Apple menu */
  277.             if (loval != 1) {                               /* if this was not About, it's a DA */
  278.                 DoDaCall(gAppleMenuHandle, loval);
  279.             } else {
  280.                 Alert(kAboutBox, nil);                      /* do about box */
  281.             }
  282.             returnVal = true;
  283.             break;
  284.         case kFileMenu:                                     /* File menu */
  285.             switch (loval) {
  286.                 case kQuitItem:
  287.                     gQuit = true;                           /* only  item */
  288.                     returnVal = true;
  289.                     break;
  290.                 default:
  291.                     break;
  292.             }
  293.             break;
  294.         case kEditMenu:
  295.             /* edit menu junk */
  296.             /* don't care */
  297.             break;
  298.         case kToolsMenu:
  299.             /* add all your test stuff here */
  300.             /* only one item, kill stuff */
  301.             KillEveryBody();
  302.             break;
  303.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  304.             /* I only care about this item.  If anything else is returned here, I don't know what */
  305.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  306.             /* Apple reserves the right to add and change things in the Help menu */
  307.             if (loval == gHelpItem)
  308.                 SampleHelpDialog();
  309.             break;
  310.             
  311.     }
  312.     HiliteMenu(0);
  313.     return(returnVal);
  314. }
  315.  
  316. /* InitAEStuff installs my appleevent handlers */
  317. void InitAEStuff(void)
  318. {
  319.     static AEinstalls HandlersToInstall[] =  {
  320.         {
  321.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  322.         },  {
  323.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  324.         },  {
  325.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  326.         },  {
  327.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  328.         }, 
  329.         /* The above are the four required AppleEvents. */
  330.         
  331.     };
  332.     
  333.     OSErr aevtErr = noErr;
  334.     long aLong = 0;
  335.     Boolean gHasAppleEvents = false;
  336.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  337.     *   then we exit */
  338.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  339.     /* The following series of calls installs all our AppleEvent Handlers.
  340.     *   These handlers are added to the application event handler list that 
  341.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  342.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  343.     *   list of handlers and dispatch to it if there is one.
  344.     */
  345.     if (gHasAppleEvents) {
  346.         register qq;
  347.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  348.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  349.                                             HandlersToInstall[qq].theProc, 0, false);
  350.             if (aevtErr) {
  351.                 ExitToShell();                              /* just fail, baby */
  352.             }
  353.         }
  354.     } else {
  355.         ExitToShell();
  356.     }
  357. }
  358.  
  359. /* end InitAEStuff */
  360. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  361. /* easy for me to say, huh? */
  362. void DoHighLevel(EventRecord *AERecord)
  363. {
  364.     
  365.     AEProcessAppleEvent(AERecord);
  366.     
  367. }
  368.  
  369. /* end DoHighLevel */
  370.  
  371. /* This is the standard Open Application event.  */
  372. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  373. {
  374. #pragma unused (messagein,reply,refIn)
  375.     /* we of course don't do anything here in this simple app */
  376.     /* except open our window */
  377.     myWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  378.     return(noErr);
  379. }
  380.  
  381. /* end AEOpenHandler */
  382.  
  383. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  384. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  385. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  386. /* handler will get called. Which means you don't do any initialization of globals here, or */
  387. /* anything else except open then doc.  */
  388. /* SO-- Do NOT assume that you are at app start time in this */
  389. /* routine, or bad things will surely happen to you. */
  390.  
  391. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  392. {
  393. #pragma unused (messagein,refIn,reply)
  394.     /* we of course don't do anything here */
  395.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  396. }
  397.  
  398. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  399. {                                                           /* no printing handler in yet, so we'll ignore this */
  400.     /* the operation is functionally identical to the ODOC event, with the additon */
  401.     /* of calling your print routine.  */
  402. #pragma unused (messagein,refIn,reply)
  403.     /* we of course don't do anything here */
  404.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  405. }
  406.  
  407. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  408. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  409. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  410. {
  411. #pragma unused (messagein,refIn,reply)
  412.     
  413.     /* prepQuit sets the Stop flag for us.  It does _NOT_ quit, you */
  414.     /* should NEVER quit from an AppleEvent handler.  Calling */
  415.     /* ExitToShell here would blow things up */
  416.     gQuit = true;
  417.     return(noErr);
  418. }
  419.  
  420.  
  421. /* This is my sample help dialog.  Does not do anything, expand as you need */
  422. void SampleHelpDialog(void)
  423. {
  424.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  425.     short itemhit = 0;
  426.     while (itemhit != 1) {
  427.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  428.     }
  429.     DisposDialog(tdial);
  430. }
  431.  
  432.  
  433. /* This is the killer code.  It finds and kills every other  */
  434. /* application on your machine. */
  435. void KillEveryBody(void)
  436. {
  437.     ProcessSerialNumber myProc, processSN;
  438.     ProcessSerialNumber finderPSN;
  439.     ProcessInfoRec infoRec;
  440.     Str31 processName;
  441.     FSSpec procSpec;
  442.     WindowPtr tempWP;    
  443.     OSErr myErr = noErr;
  444.     OSErr otherError;
  445.     AppleEvent theEvent;
  446.     AEDesc theAddress;
  447.     Boolean ourFlag, notFinder;
  448.     Boolean finderFound = false;
  449.     GetCurrentProcess(&myProc);
  450.     /* Preset the PSN to no PSN, see IM VI, the Process Manager */
  451.     processSN.lowLongOfPSN = kNoProcess;
  452.     processSN.highLongOfPSN = kNoProcess;
  453.     finderPSN.lowLongOfPSN = nil;
  454.     finderPSN.highLongOfPSN = nil;
  455.     
  456.     do {
  457.         myErr = GetNextProcess(&processSN);
  458.         SameProcess(&myProc, &processSN, &ourFlag);
  459.         if (!ourFlag && !finderFound) {
  460.             /* see if it's the Finder, we have to kill the finder LAST */
  461.             /* or else non-sys 7 apps won't get killed */
  462.             /* since the Finder must be there to convert the AppleEvent to Puppet Strings */
  463.             /* if the app is not APpleEvent aware */
  464.             infoRec.processInfoLength = sizeof(ProcessInfoRec);
  465.             infoRec.processName = &processName;
  466.             infoRec.processAppSpec = &procSpec;
  467.             GetProcessInformation(&processSN, &infoRec);
  468.             if (infoRec.processSignature == 'MACS' && infoRec.processType == 'FNDR') {
  469.                 /* save this number for later  */
  470.                 finderPSN = processSN;
  471.                 notFinder = false;
  472.             } else {
  473.                 notFinder = true;
  474.                 finderFound = true;
  475.             }
  476.         }
  477.         if (!myErr && !ourFlag && notFinder) {
  478.             otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&processSN, sizeof(processSN), &theAddress);
  479.             if (!otherError)
  480.                 otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,
  481.                                                 kAnyTransactionID, &theEvent);
  482.             if (!otherError)
  483.                 AEDisposeDesc(&theAddress);
  484.             /* Again, the Finder will convert the AppleEvent to puppetstrings if */
  485.             /* the application is a System 6 or non-AE aware app.  This ONLY  */
  486.             /* happens for the 4 required (oapp,odoc,pdoc, and quit) AppleEvents  */
  487.             /* and ONLY if you use the PSN for the address */
  488.             if (!otherError)
  489.                 AESend(&theEvent, nil, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
  490.                        nil, nil);
  491.             AEDisposeDesc(&theEvent);
  492.         }
  493.     }
  494.             while (!myErr);
  495.     /* Now, if the finder was running, it's safe to kill it */
  496.     if (finderPSN.lowLongOfPSN || finderPSN.highLongOfPSN) {
  497.         otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(processSN), &theAddress);
  498.         if (!otherError)
  499.             otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,
  500.                                             kAnyTransactionID, &theEvent);
  501.         if (!otherError)
  502.             AEDisposeDesc(&theAddress);
  503.         if (!otherError)
  504.             AESend(&theEvent, nil, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, nil,
  505.                    nil);
  506.         AEDisposeDesc(&theEvent);
  507.     }
  508. GetPort(&tempWP);
  509. SetPort(myWindow);
  510. InvalRect(&myWindow->portRect);
  511. SetPort(tempWP);
  512. }
  513.  
  514.  
  515. #pragma segment Initialize
  516. void InitalizeApp(void)
  517. {
  518.     MenuHandle helpHandle;
  519.     StringHandle helpString;
  520.     short count;
  521.     long vers;
  522.     MaxApplZone();
  523.     InitGraf((Ptr)&qd.thePort);
  524.     InitFonts();
  525.     InitWindows();
  526.     InitMenus();
  527.     TEInit();
  528.     InitDialogs(nil);
  529.     InitCursor();
  530.     /* Check system version */
  531.     Gestalt(gestaltSystemVersion, &vers);
  532.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  533.     if (vers < 7) {
  534.         StopAlert(kBadSystem, nil);
  535.         ExitToShell();
  536.     }
  537.     InitAEStuff();
  538.     /* set up my menu junk */
  539.     gMymenu = GetNewMBar(kMBarID);
  540.     SetMenuBar(gMymenu);
  541.     gAppleMenuHandle = GetMHandle(kAppleMenu);
  542.     gFileMenuHandle = GetMHandle(kFileMenu);
  543.     gEditMenuHandle = GetMHandle(kEditMenu);
  544.     gToolMenuHandle = GetMHandle(kToolsMenu);
  545.     AddResMenu(gAppleMenuHandle, 'DRVR');
  546.     /* now install my Help menu item in the Help Manager's menu */
  547.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  548.     count = CountMItems(helpHandle);                        /* How many items are there? */
  549.     helpString = GetString(kHelpString);                    /* get my help string */
  550.     DetachResource(helpString);                             /* detach it */
  551.     HNoPurge(helpString);
  552.     MoveHHi((Handle)helpString);
  553.     HLock((Handle)helpString);
  554.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  555.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  556.     
  557.     DrawMenuBar();
  558.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  559.     
  560.     
  561. }
  562.